﻿namespace Atomic.Extensions
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Security.Cryptography;
    using System.Text;
    using System.Text.RegularExpressions;

    /// <summary>
    /// 字符串扩展。
    /// </summary>
    public static class StringExtensions
    {
        /// <summary>
        /// 验证 Web URL 的正则表达式。
        /// </summary>
        private static readonly Regex WebUrlExpression = new Regex(@"(http|https)://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?", RegexOptions.Singleline | RegexOptions.Compiled);
        
        /// <summary>
        /// 验证 Email 的正则表达式。
        /// </summary>
        private static readonly Regex EmailExpression = new Regex(@"^([0-9a-zA-Z]+[-._+&])*[0-9a-zA-Z]+@([-0-9a-zA-Z]+[.])+[a-zA-Z]{2,6}$", RegexOptions.Singleline | RegexOptions.Compiled);
        
        /// <summary>
        /// 验证 Html 的正则表达式。
        /// </summary>
        private static readonly Regex StripHTMLExpression = new Regex("<\\S[^><]*>", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Multiline | RegexOptions.CultureInvariant | RegexOptions.Compiled);

        /// <summary>
        /// 当前字符串是 null 还是 System.String.Empty 字符串。
        /// </summary>
        /// <param name="target">当前字符串。</param>
        /// <returns>是否为空。</returns>
        public static bool IsNullOrEmpty(this string target)
        {
            return string.IsNullOrEmpty(target);
        }

        /// <summary>
        /// 指示指定的字符串是 null、空还是仅由空白字符组成。
        /// </summary>
        /// <param name="target">当前字符串。</param>
        /// <returns>如果 value 参数为 null 或 System.String.Empty，或者如果 value 仅由空白字符组成，则为 true。</returns>
        public static bool IsNullOrWhiteSpace(this string target)
        {
            return string.IsNullOrWhiteSpace(target);
        }

        /// <summary>
        /// 判断对象是否为 System.Int32 类型的数字。
        /// </summary>
        /// <param name="target">当前字符串。</param>
        /// <returns>如果 target 参数为 System.Int32 类型的数字，则为 true。</returns>
        public static bool IsNumeric(this string target)
        {
            if (!string.IsNullOrWhiteSpace(target))
            {
                if (target.Length > 0 && Regex.IsMatch(target, @"^[-]?[0-9]*[.]?[0-9]*$"))
                {
                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// 验证当前字符串是否为 System.DateTime 类型。
        /// </summary>
        /// <param name="target">当前字符串。</param>
        /// <returns>如果 target 参数为 System.DateTime 类型，则为 true。</returns>
        public static bool IsDateTime(this string target)
        {
            if (!string.IsNullOrWhiteSpace(target))
            {
                if (target.Length > 0 && Regex.IsMatch(target, @"^((\d{2}(([02468][048])|([13579][26]))[\-\/\s]((((0?[13578])|(1[02]))[\-\/\s]((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\-\/\s]((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\-\/\s]((0?[1-9])|([1-2][0-9])))))|(\d{2}(([02468][1235679])|([13579][01345789]))[\-\/\s]((((0?[13578])|(1[02]))[\-\/\s]((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\-\/\s]((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\-\/\s]((0?[1-9])|(1[0-9])|(2[0-8]))))))(\s(((0?[0-9])|(2[0-3])|(1[0-9]))\:([0-5]?[0-9])((\s)|(\:([0-5]?[0-9])))))?$"))
                {
                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// 判断当前字符串是否在指定的范围内。
        /// </summary>
        /// <param name="target">当前字符串。</param>
        /// <param name="minLength">最小长度。</param>
        /// <param name="maxLength">最大长度。</param>
        /// <returns>在指定的范围内，则为 true。</returns>
        public static bool Range(this string target, int minLength, int maxLength)
        {
            return !string.IsNullOrWhiteSpace(target) && target.Length >= minLength && target.Length <= maxLength;
        }

        /// <summary>
        /// 对进当字符串进行哈希。
        /// </summary>
        /// <param name="target">当前字符串。</param>
        /// <returns>哈希值。</returns>
        public static string Hash(this string target)
        {
            using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
            {
                byte[] data = Encoding.Unicode.GetBytes(target);
                byte[] hash = md5.ComputeHash(data);

                return Convert.ToBase64String(hash);
            }
        }

        /// <summary>
        /// 将当前字符串转换成 32 位 MD5 加密。
        /// </summary>
        /// <param name="target">当前字符串。</param>
        /// <returns>32 位 MD5 加密后的字符串。</returns>
        public static string MD5(this string target)
        {
            return target.MD5("Atomic", "UTF-8");
        }

        /// <summary>
        /// 将当前字符串转换成 32 位 MD5 加密。
        /// </summary>
        /// <param name="target">当前字符串。</param>
        /// <param name="key">密钥。</param>
        /// <param name="charset">编码格式。</param>
        /// <returns>32 位 MD5 加密后的字符串。</returns>
        public static string MD5(this string target, string key, string charset)
        {
            StringBuilder md5Text = new StringBuilder(32);

            target += key;

            System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
            byte[] t = md5.ComputeHash(Encoding.GetEncoding(charset).GetBytes(target));
            for (int i = 0; i < t.Length; i++)
            {
                md5Text.Append(t[i].ToString("x").PadLeft(2, '0'));
            }

            return md5Text.ToString();
        }

        /// <summary>
        /// 是否电子邮箱。
        /// </summary>
        /// <param name="target">当前字符串。</param>
        /// <returns>是否电子邮箱。</returns>
        public static bool IsEmail(this string target)
        {
            if (!string.IsNullOrEmpty(target))
            {
                return EmailExpression.IsMatch(target);
            }

            return false;
        }

        /// <summary>
        /// 指示 System.Text.RegularExpressions.Regex 构造函数中指定的正则表达式在指定的输入字符串中是否找到了匹配项。
        /// </summary>
        /// <param name="target">当前字符串。</param>
        /// <param name="expressionString">正则表达式。</param>
        /// <returns>验证通过，则为 True。</returns>
        public static bool IsMatch(this string target, string expressionString)
        {
            if (!string.IsNullOrWhiteSpace(target))
            {
                Regex expression = new Regex(expressionString);
                return expression.IsMatch(target);
            }

            return false;
        }

        /// <summary>
        /// 获取字符串真实长度。
        /// </summary>
        /// <remarks>1个汉字等于2个字符。</remarks>
        /// <param name="text">当前字符串。</param>
        /// <returns>字符串真实长度。</returns>
        public static int Length(this string text)
        {
            return Encoding.Default.GetBytes(text).Length;
        }

        /// <summary>
        /// 判断指定字符串在指定字符串数组中的位置。
        /// </summary>
        /// <param name="strSearch">当前字符串。</param>
        /// <param name="stringArray">字符串数组。</param>
        /// <param name="caseInsensetive">是否不区分大小写，true 为不区分，false 为区分。</param>
        /// <returns>字符串在指定字符串数组中的位置，如不存在则返回 -1。</returns>
        public static int TextFromArrayIndex(this string strSearch, string[] stringArray, bool caseInsensetive)
        {
            for (int i = 0; i < stringArray.Length; i++)
            {
                if (caseInsensetive)
                {
                    if (strSearch.ToLower() == stringArray[i].ToLower())
                        return i;
                }
                else if (strSearch == stringArray[i])
                    return i;
            }
            return -1;
        }
    }
}